﻿using System;
using System.Collections;
using Microsoft.DirectX;
using Microsoft.DirectX.Direct3D;

namespace DirectXSim
{
    public class Game
    {
        private TimeSpan _totalTime;
        private TimeSpan _lapTime;
        
        private int _totalLaps;

        private DateTime _startTime;
        private DateTime _lapStartTime;
        private bool _finished = false;
        private bool _initializing = true;
        private bool _noCollisionMode = false;
        private int _racers;
        
        private ArrayList _carList = new ArrayList();

        private Track _track;
                
        public Game(int numLaps)
        {
            _totalTime = new TimeSpan(0, 0, 0, 0, 0);
            _lapTime = new TimeSpan(0, 0, 0, 0, 0);
            _racers = 0;
            _totalLaps = numLaps;
        }

        public void LoadTrack(ref Device dev)
        {
            _track = new Track(ref dev);
        }

        public void AddCar(float startx, float starty, float startz)
        {
            Car theCar = new Car(startx, starty, startz);
            _carList.Add(theCar);
            _racers++;
        }

        public void Start()
        {
            _startTime = DateTime.Now;
            _lapStartTime = DateTime.Now;
        }

        public Car MyCar
        {
            get { return (Car)_carList[0]; }
        }

        public int TotalLaps
        {
            get { return _totalLaps; }
        }

        public int TotalRacers
        {
            get { return _racers; }
        }

        public Car OpponentCar
        {
            get { return (Car)_carList[1]; }
        }

        public Track Track
        {
            get { return _track; }
        }

        public bool Finished
        {
            get { return _finished; }
        }

        public bool Initializing
        {
            get { return _initializing; }
            set { _initializing = value; }
        }

        public TimeSpan TotalTime
        {
            get { return _totalTime; }
        }

        public TimeSpan LapTime
        {
            get { return _lapTime; }
        }

        public void CheckCarPositions()
        {
            if (MyCar.Position.Y >= (_track.Height - MyCar.Radius))
            {
                //Reached end of grid - update lap
                MyCar.LapNumber++;
                //Check lap time - if end of first lap or new best, update best
                _lapTime = DateTime.Now - _lapStartTime;
                if (_lapTime < MyCar.BestLapTime || MyCar.LapNumber == 2)
                {
                    MyCar.BestLapTime = _lapTime;
                }
                if (MyCar.LapNumber >= _totalLaps)
                {
                    _finished = true;
                }
                else
                {
                    //Reset position
                    MyCar.ResetPosition();
                    _lapStartTime = DateTime.Now;
                }
            }
            if (OpponentCar.Position.Y >= (_track.Height - OpponentCar.Radius))
            {

                //Reached end of grid - update lap
                OpponentCar.LapNumber++;
                if (OpponentCar.LapNumber > _totalLaps)
                {
                    _finished = true;
                }
                else
                {
                    //Reset position
                    OpponentCar.ResetPosition();
                 }
            }

            if (!_initializing)
            {
                _totalTime = DateTime.Now - _startTime;
                _lapTime = DateTime.Now - _lapStartTime;
            }

            if (OpponentCar.LapNumber >= MyCar.LapNumber && OpponentCar.Position.Y > MyCar.Position.Y)
            {
                MyCar.RacePosition = 2;
            }
            else
            {
                MyCar.RacePosition = 1;
            }
        }


        internal void CheckCollisions()
        {
            if (_noCollisionMode == false)
            {
                //Check if hit opponent car(s)
                if (Math.Sqrt(Math.Pow(OpponentCar.Position.X - MyCar.Position.X, 2) + Math.Pow(OpponentCar.Position.Y - MyCar.Position.Y, 2) + Math.Pow(OpponentCar.Position.Z - MyCar.Position.Z, 2)) < MyCar.Radius + OpponentCar.Radius)
                {
                    MyCar.HandleCollision(CollisionType.Opponent, _track.Width);
                }
                else
                {
                    MyCar.HandleCollision(_track.CheckTrackCollision(MyCar.Position, MyCar.Radius), _track.Width);
                }
            }
            ItemType myCarItem = _track.CheckBonusItemPickup(MyCar.Position, MyCar.Radius);

            if (myCarItem == ItemType.NoCollision)
            {
                _noCollisionMode = true;
            }
            else if (myCarItem != ItemType.None)
            {
                _noCollisionMode = false;
            }


            //if (myCarItem != ItemType.None && myCarItem == ItemType.NoCollision)
            //{
            //    _noCollisionMode = false;
            //}
            //else
            //{
            //    _noCollisionMode = true;
            //}
            MyCar.HandlePickUp(myCarItem);

            OpponentCar.HandleCollision(_track.CheckTrackCollision(OpponentCar.Position, MyCar.Radius),_track.Width);


        }
    }
}
